
#ifndef __ENCODER_CALIBRATION_H__
#define __ENCODER_CALIBRATION_H__

#include <stdio.h>
#include <stdbool.h>
#include <math.h>
#include <stdlib.h>
#include "log.h"
#include "tb67h450.h"
#include "mt6816.h"
#include "stockpile_f103cb.h"

#define MOTOR_ONE_CIRCLE_HARD_STEPS ((int)200)
#define SOFT_DIVIDE_NUM ((int)256)
#define MOTOR_ONE_CIRCLE_SUBDIVIDE_STEPS ((int)(MOTOR_ONE_CIRCLE_HARD_STEPS * SOFT_DIVIDE_NUM))

#define CAL_CURRENT ((int)2000)
#define AUTO_CAL_SPEED ((int)2)
#define FINE_TUNE_CAL_SPEED ((int)1)

#define ENCODER_RANGE (int)16384 // 2^14 = 16384

typedef enum {
    CAL_CONTROL_DISABLE = 0x00, // 失能
    CAL_FORWARD_PREPARE,        // 准备正转自动校准编码器
    CAL_FORWARD_MEASURE,        // 正向测量
    CAL_BACKWARD_RETURN,        // 反向回退
    CAL_BACKWARD_GAP_DISMISS,   // 反向消差
    CAL_BACKWARD_MEASURE,       // 反向测量
    CAL_CALCULATING,            // 数据解算
} CAL_StateTypeDef;

typedef enum {
    CAL_NO_ERROR = 0x00,         // 数据无错误
    CAL_ERROR_AVERAGE_DIR,       // 平均值方向错误
    CAL_ERROR_AVERAGE_CONTINUTY, // 平均值连续性错误
    CAL_ERROR_PHASE_STEP,        // 阶跃次数错误，用于寻找电机开始位置，因为电机不一定从 0 位置开始采集数据
    CAL_ERROR_ANALYSIS_QUANTITY, // 解析数据量错误
} CAL_ErrorTypeDef;

#define SAMPLE_COUNTS_PER_STEP 16 // 每个采集点采集数量

typedef struct {
    unsigned char isTriggered;  // 是否开启校准
    CAL_ErrorTypeDef errorCode; // 校准错误代码
    unsigned int errorData;     // 校准错误数据

    // 编码器数据读取过程
    CAL_StateTypeDef state;                                        // 正在进行的校准步骤
    unsigned int goPosition;                                       // 输出位置
    unsigned short sampleRawCount;                                 // 原始数据采集计数
    unsigned short sampleRawData[SAMPLE_COUNTS_PER_STEP];          // 同一采集点，多次采集点的数据
    unsigned short sampleAverageCount;                             // 多次采集点平均值计数
    unsigned short sampleAverageDataForward[MOTOR_ONE_CIRCLE_HARD_STEPS + 1];  // 正向校准读取的数据，实际采集 201 个数据 (index:0-200)
    unsigned short sampleAverageDataBackward[MOTOR_ONE_CIRCLE_HARD_STEPS + 1]; // 反向校准读取的数据，实际采集 201 个数据 (index:0-200)
    unsigned char goDirection;                                     // 电机运行方向，方向不同采集到的数据排列规律不同

    // 编码器数据处理过程
    int rcdX, rcdY; // 寻找区间下标及阶跃差值，用于寻找电机开始位置，因为电机不一定从 0 位置开始采集数据
    unsigned int resultNum; // 统计校准数据数量
} CAL_HandleTypeDef;

extern CAL_HandleTypeDef calHandle;

extern int dataBufAverage(unsigned short * buffer, unsigned int len);
extern void encoderCALInit();
extern void encoderCALController();
extern void encoderCALDataCalc();

#endif
